/**
 * Copyright (c) 2018, wuyy All rights reserved.
 * wuyy 专有/保密源代码,未经许可禁止任何人通过任何渠道使用、修改源代码.
 * QQ:16349023
 * 项目名称 : com.wy2.eclipse.tool.ui
 * @version V1.0
 */
package com.wy2.eclipse.tool.ui.wizard;

import java.io.File;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import com.ibm.icu.lang.UCharacter;
import com.wy2.core.tool.StringTools;
import com.wy2.eclipse.tool.lib.TemplateConfigManager;
import com.wy2.eclipse.tool.lib.entity.ProjectGenerateContext;
import com.wy2.eclipse.tool.lib.entity.TemplateConfig;
import com.wy2.eclipse.tool.lib.entity.TemplateItem;
import com.wy2.eclipse.tool.ui.UIActivator;
import com.wy2.eclipse.tool.ui.editors.CodeTemplateContentProvider;
import com.wy2.eclipse.tool.ui.editors.CodeTemplateLabelProvider;
import com.wy2.eclipse.tool.ui.preferences.PreferenceConstants;
import com.wy2.eclipse.tool.ui.resource.Messages;

/**
 * 项目生成向导 基础页
 * @author wuyy<16349023@qq.com>
 * @date 2018年1月30日上午9:12:13
 * 
 */
public class ProjectGenerateBasePage extends WizardPage {

    private Button useDefaultWorkspaceLocationButton;
    private Label locationLabel;
    private Combo locationCombo;
    private Button locationBrowseButton;
    private ComboViewer comboViewerTemplateName;
    
    /** group id text field */
    protected Combo groupIdCombo;

    /** artifact id text field */
    protected Text artifactIdText;

    /** version text field */
    protected Combo versionCombo;

    /** package text field */
    protected Combo packageCombo;
    
    
    private IPath location;
    private final ProjectGenerateContext projectGenerateContext;
    private IStructuredSelection selection;
    
    
    /**
     * Create the wizard.
     */
    public ProjectGenerateBasePage(final ProjectGenerateContext projectGenerateContext) {
        super("wizardPage");
        setTitle(Messages.getString("wy2.ProjectGenerateWizard.WizardPage.title"));
        setDescription(Messages.getString("wy2.ProjectGenerateWizard.WizardPage.desc"));
        this.projectGenerateContext=projectGenerateContext;
        setPageComplete(false);
    }

    /**
     * Create contents of the wizard.
     * @param parent
     */
    public void createControl(Composite parent) {
        Composite container = new Composite(parent, SWT.NONE);
        
        GridLayout layout = new GridLayout();
        container.setLayout(layout);
        layout.numColumns = 3;
        layout.verticalSpacing = 9;
        
        useDefaultWorkspaceLocationButton = new Button(container, SWT.CHECK);
        GridData useDefaultWorkspaceLocationButtonData = new GridData(SWT.LEFT, SWT.CENTER, false, false, 3, 1);
        useDefaultWorkspaceLocationButton.setLayoutData(useDefaultWorkspaceLocationButtonData);
        useDefaultWorkspaceLocationButton.setText("默认工作空间");
        useDefaultWorkspaceLocationButton.addSelectionListener(new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            boolean inWorkspace = isInWorkspace();
            locationLabel.setEnabled(!inWorkspace);
            locationCombo.setEnabled(!inWorkspace);
            locationBrowseButton.setEnabled(!inWorkspace);
            validate();
          }
        });
        useDefaultWorkspaceLocationButton.setSelection(true);
        
        locationLabel = new Label(container, SWT.NONE);
        GridData locationLabelData = new GridData();
        locationLabelData.horizontalIndent = 10;
        locationLabel.setLayoutData(locationLabelData);
        locationLabel.setText("位置");
        locationLabel.setEnabled(false);

        locationCombo = new Combo(container, SWT.NONE);
        GridData locationComboData = new GridData(SWT.FILL, SWT.CENTER, true, false);
        locationCombo.setLayoutData(locationComboData);
        locationCombo.setEnabled(false);

        locationBrowseButton = new Button(container, SWT.NONE);
        GridData locationBrowseButtonData = new GridData(SWT.FILL, SWT.CENTER, false, false);
        locationBrowseButton.setLayoutData(locationBrowseButtonData);
        locationBrowseButton.setText("浏览");
        locationBrowseButton.addSelectionListener(new SelectionAdapter() {
          public void widgetSelected(SelectionEvent e) {
            DirectoryDialog dialog = new DirectoryDialog(getShell());
            dialog.setText("选择项目生成位置");

            String path = locationCombo.getText();
            if(path.length() == 0) {
              path = ResourcesPlugin.getWorkspace().getRoot().getLocation().toPortableString();
            }
            dialog.setFilterPath(path);

            String selectedDir = dialog.open();
            if(selectedDir != null) {
              locationCombo.setText(selectedDir);
              validate();
            }
          }
        });
        locationBrowseButton.setEnabled(false);
        
        if(location == null || Platform.getLocation().equals(location)) {
            locationCombo.setText(Platform.getLocation().toOSString());
        } else {
          locationCombo.setText(location.toOSString());
        }
        
        {
            Label lblNewLabel = new Label(container, SWT.NONE);
            lblNewLabel.setText("选择生成模板");
            GridData gd = new GridData(SWT.RIGHT, SWT.CENTER, false, false);
            lblNewLabel.setLayoutData(gd);
        }
        {

            comboViewerTemplateName = new ComboViewer(container, SWT.NONE | SWT.READ_ONLY);
            Combo comboTemplateName = comboViewerTemplateName.getCombo();
            comboTemplateName.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false,2,1));
            comboViewerTemplateName.setContentProvider(new ProjectTemplateContentProvider());
            comboViewerTemplateName.setLabelProvider(new CodeTemplateLabelProvider());   
        }
        {
            Label groupIdlabel = new Label(container, SWT.NONE);
            groupIdlabel.setText("GroupId");

            groupIdCombo = new Combo(container, SWT.BORDER);
            groupIdCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
            groupIdCombo.setData("name", "groupId"); //$NON-NLS-1$ //$NON-NLS-2$
            //groupIdCombo.setText("GroupId");
            groupIdCombo.addModifyListener(new ModifyListener() {

                @Override
                public void modifyText(ModifyEvent e) {
                  validate();
                  //重设基础包路径
                  String packageName=getDefaultJavaPackage(groupIdCombo.getText(), artifactIdText.getText());
                  packageCombo.setText(packageName);
                }
            });

            Label artifactIdLabel = new Label(container, SWT.NONE );
            artifactIdLabel.setText("ArtifactId");

            artifactIdText = new Text(container, SWT.BORDER );
            artifactIdText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
            artifactIdText.setData("name", "artifactId"); //$NON-NLS-1$ //$NON-NLS-2$
            artifactIdText.addModifyListener(new ModifyListener() {
                
                @Override
                public void modifyText(ModifyEvent e) {
                    validate();
                  //重设基础包路径
                    String packageName=getDefaultJavaPackage(groupIdCombo.getText(), artifactIdText.getText());
                    packageCombo.setText(packageName);
                }
            });


            Label versionLabel = new Label(container, SWT.NONE);
            versionLabel.setText("Version");

            versionCombo = new Combo(container, SWT.BORDER);
            GridData gd_versionCombo = new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1);
            //gd_versionCombo.widthHint = 150;
            versionCombo.setLayoutData(gd_versionCombo);
            //versionCombo.setText(StaticResource.DEFAULT_VERSION);
            versionCombo.addModifyListener(new ModifyListener() {
                public void modifyText(ModifyEvent e) {
                    validate();
                }
            });

            Label packageLabel = new Label(container, SWT.NONE);
            packageLabel.setText("package");

            packageCombo = new Combo(container, SWT.BORDER);
            packageCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
            packageCombo.setData("name", "package"); //$NON-NLS-1$ //$NON-NLS-2$
            packageCombo.addModifyListener(new ModifyListener() {
                public void modifyText(ModifyEvent e) {
                    validate();
                }
            });
        }

        dataBinding();
        setControl(container);
    }
    
    private void dataBinding() {
        IPreferenceStore store = UIActivator.getDefault().getPreferenceStore();
        groupIdCombo.setText(store.getString(PreferenceConstants.P_PROJECT_DEFAULT_GROUPID));
        versionCombo.setText(store.getString(PreferenceConstants.P_PROJECT_DEFAULT_VERSION));
        
        TemplateConfigManager templateConfigManager=UIActivator.getDefault().getTemplateConfigManager();
        if(templateConfigManager.templateConfigExists()) {
            TemplateConfig templateConfig = templateConfigManager.loadTemplateConfig();
            if(templateConfig!=null) {
                comboViewerTemplateName.setInput(templateConfig);
                comboViewerTemplateName.getCombo().select(0);
            }
        }
    }
    
    public boolean isInWorkspace() {
        return useDefaultWorkspaceLocationButton.getSelection();
    }

    /**
     * Returns the path of the location where the project is to be created.
     * According to the user input, the path either points to the workspace or to a
     * valid user specified location on the filesystem.
     * 
     * @return The path of the location where to create the project. Is never
     *         <code>null</code>.
     */
    public IPath getLocationPath() {
        if (isInWorkspace()) {
            return ResourcesPlugin.getWorkspace().getRoot().getLocation();
        }
        return Path.fromOSString(locationCombo.getText().trim());
    }

    public void setLocationPath(IPath location) {
        this.location = location;
    }
    
    private boolean isVisible() {
        return getControl() != null && getControl().isVisible();
    }

    void validate() {
        if (isVisible()) {
            
            //
            String error = validateInput();
            setErrorMessage(error);
            if(StringTools.isEmpty(error)) {
                projectGenerateContext.setLocationPath(getLocationPath().toOSString());
                
                Object template = comboViewerTemplateName.getStructuredSelection().getFirstElement();
                projectGenerateContext.setTemplate((TemplateItem) template);
                projectGenerateContext.setGroupId(groupIdCombo.getText().trim());
                projectGenerateContext.setArtifactId(artifactIdText.getText().trim());
                projectGenerateContext.setVersion(versionCombo.getText().trim());
                projectGenerateContext.setPackages(packageCombo.getText().trim());
            }
            setPageComplete(error == null);
        }
    }
    private String validateInput() {
        String error = validateGroupIdInput(groupIdCombo.getText());
        if (error != null) {
            return error;
        }

        error = validateArtifactIdInput(artifactIdText.getText());
        if (error != null) {
            return error;
        }

        String versionValue = versionCombo.getText();
        if (versionValue.length() == 0) {
            return Messages.getString("wy2.ProjectGenerateWizard.WizardPage.error.version01");
        }
        // TODO: check validity of version?

        String packageName = packageCombo.getText();
        if (packageName.trim().length() == 0
                || !Pattern.matches("[A-Za-z_$][A-Za-z_$\\d]*(?:\\.[A-Za-z_$][A-Za-z_$\\d]*)*", packageName)) {
            return Messages.getString("wy2.ProjectGenerateWizard.WizardPage.error.package01");
        }

        return null;
    }
    
    public static String getDefaultJavaPackage(String groupId, String artifactId) {
        StringBuilder sb = new StringBuilder(groupId);

        if (sb.length() > 0 && artifactId.length() > 0) {
            sb.append('.');
        }

        sb.append(artifactId);

        boolean isFirst = true;
        StringBuilder pkg = new StringBuilder();
        for (int i = 0; i < sb.length(); i++) {
            char c = sb.charAt(i);
            if (c == '-') {
                pkg.append('_');
                isFirst = false;
            } else {
                if (isFirst) {
                    if (UCharacter.isJavaIdentifierStart(c)) {
                        pkg.append(c);
                        isFirst = false;
                    }
                } else {
                    if (c == '.') {
                        pkg.append('.');
                        isFirst = true;
                    } else if (UCharacter.isJavaIdentifierPart(c)) {
                        pkg.append(c);
                    }
                }
            }
        }

        return pkg.toString();
    }

    protected String validateArtifactIdInput(String text) {
        return validateIdInput(text, true);
    }

    protected String validateGroupIdInput(String text) {
        return validateIdInput(text, false);
    }

    
    private String validateIdInput(String text, boolean artifact) {
        if (text == null || text.length() == 0) {
            return artifact ? Messages.getString("wy2.ProjectGenerateWizard.WizardPage.error.artifactid01")
                    : Messages.getString("wy2.ProjectGenerateWizard.WizardPage.error.groupid01");
        }

        if (text.contains(" ")) { //$NON-NLS-1$
            return artifact ? Messages.getString("wy2.ProjectGenerateWizard.WizardPage.error.artifactid02")
                    : Messages.getString("wy2.ProjectGenerateWizard.WizardPage.error.groupid02");
        }
        

        IStatus nameStatus = ResourcesPlugin.getWorkspace().validateName(text, IResource.PROJECT);
        if (!nameStatus.isOK()) {
            return Messages.getString(artifact ? "wy2.ProjectGenerateWizard.WizardPage.error.artifactid03"
                    : "wy2.ProjectGenerateWizard.WizardPage.error.groupid03", nameStatus.getMessage());
        }

        if (!text.matches("[A-Za-z0-9_\\-.]+")) { //$NON-NLS-1$
            return Messages.getString(artifact ? "wy2.ProjectGenerateWizard.WizardPage.error.artifactid03"
                    : "wy2.ProjectGenerateWizard.WizardPage.error.groupid03", nameStatus.getMessage());
        }
        if(artifact) {
            //是否已存在项目做检测
            File projectDirectory = new File(getLocationPath() + File.separator + text);
            if(projectDirectory.exists()) {
                return Messages.getString("wy2.ProjectGenerateWizard.WizardPage.error.artifactid00");
            }
        }

        return null;
    }
}
